package org.jeecg.modules.wms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.UUIDGenerator;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.wms.entity.WmsInventory;
import org.jeecg.modules.wms.entity.WmsInventoryHistory;
import org.jeecg.modules.wms.entity.WmsMaterial;
import org.jeecg.modules.wms.entity.WmsWarehouse;
import org.jeecg.modules.wms.entity.WmsWarehouseLocation;
import org.jeecg.modules.wms.mapper.WmsInventoryMapper;
import org.jeecg.modules.wms.service.IWmsInventoryHistoryService;
import org.jeecg.modules.wms.service.IWmsInventoryService;
import org.jeecg.modules.wms.service.IWmsMaterialService;
import org.jeecg.modules.wms.service.IWmsWarehouseLocationService;
import org.jeecg.modules.wms.service.IWmsWarehouseService;
import org.jeecg.modules.wms.vo.WmsInventoryVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 库存管理服务实现
 */
@Slf4j
@Service
public class WmsInventoryServiceImpl extends ServiceImpl<WmsInventoryMapper, WmsInventory> implements IWmsInventoryService {

    @Autowired
    private IWmsInventoryHistoryService inventoryHistoryService;

    @Autowired
    private IWmsMaterialService materialService;

    @Autowired
    private IWmsWarehouseService warehouseService;

    @Autowired
    private IWmsWarehouseLocationService locationService;

    @Override
    public IPage<WmsInventoryVO> queryInventoryPageList(Page<WmsInventoryVO> page, Map<String, Object> query) {
        IPage<WmsInventoryVO> pageList = baseMapper.queryInventoryPageList(page, query);
        // 计算库存状态
        if (pageList.getRecords() != null && !pageList.getRecords().isEmpty()) {
            // 按物料编号和型材长度分组，计算总库存
            Map<String, BigDecimal> materialTotalMap = new HashMap<>();

            // 第一次遍历，计算每个物料编号+型材长度的总库存
            for (WmsInventoryVO vo : pageList.getRecords()) {
                String materialKey = vo.getMaterialCode();
                // 如果存在型材长度，则将其作为key的一部分
                if (vo.getSpecification() != null && vo.getSpecification().contains("*")) {
                    materialKey += "_" + vo.getSpecification();
                }

                BigDecimal currentTotal = materialTotalMap.getOrDefault(materialKey, BigDecimal.ZERO);
                currentTotal = currentTotal.add(vo.getQuantity() != null ? vo.getQuantity() : BigDecimal.ZERO);
                materialTotalMap.put(materialKey, currentTotal);
            }

            // 第二次遍历，根据总库存和物料预警上下限判断库存状态
            for (WmsInventoryVO vo : pageList.getRecords()) {
                // 获取物料信息
                WmsMaterial material = materialService.getByCode(vo.getMaterialCode());
                if (material != null) {
                    String materialKey = vo.getMaterialCode();
                    // 如果存在型材长度，则将其作为key的一部分
                    if (vo.getSpecification() != null && vo.getSpecification().contains("*")) {
                        materialKey += "_" + vo.getSpecification();
                    }

                    // 获取该物料编号+型材长度的总库存
                    BigDecimal totalQuantity = materialTotalMap.getOrDefault(materialKey, BigDecimal.ZERO);

                    // 根据总库存与预警上下限比较设置库存状态
                    if (material.getUpperLimit() != null && totalQuantity.compareTo(material.getUpperLimit()) > 0) {
                        vo.setStockStatus(2); // 超过上限
                        vo.setStockStatusName("超过上限");
                    } else if (material.getLowerLimit() != null && totalQuantity.compareTo(material.getLowerLimit()) < 0) {
                        vo.setStockStatus(3); // 低于下限
                        vo.setStockStatusName("低于下限");
                    } else {
                        vo.setStockStatus(1); // 正常
                        vo.setStockStatusName("正常");
                    }
                }else {
                    vo.setStockStatus(1);
                    vo.setStockStatusName("正常");
                }
            }
        }
        return pageList;
    }

    public WmsInventory findByMaterialAndWarehouse(String materialCode, String warehouseId, String locationId) {
        return baseMapper.findByMaterialAndWarehouse(materialCode, warehouseId, locationId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean inbound(WmsInventory inventory, BigDecimal quantity, Integer businessType, String businessNo, String operator, String remark) {
        if (inventory == null) {
            throw new JeecgBootException("库存信息不能为空");
        }

        if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
            throw new JeecgBootException("入库数量必须大于0");
        }

        // 查询库存是否存在
        WmsInventory existInventory = findByMaterialAndWarehouse(inventory.getMaterialCode(), inventory.getWarehouseId(), inventory.getLocationId());

        BigDecimal beforeQuantity = BigDecimal.ZERO;
        BigDecimal afterQuantity;

        if (existInventory != null) {
            // 库存已存在，更新数量
            beforeQuantity = existInventory.getQuantity() != null ? existInventory.getQuantity() : BigDecimal.ZERO;
            afterQuantity = beforeQuantity.add(quantity);

            existInventory.setQuantity(afterQuantity);
            existInventory.setAvailableQuantity(existInventory.getAvailableQuantity() != null ?
                    existInventory.getAvailableQuantity().add(quantity) : quantity);
            existInventory.setUpdateBy(operator);
            existInventory.setUpdateTime(new Date());

            updateById(existInventory);

            // 记录库存流水
            inventoryHistoryService.recordHistory(existInventory, beforeQuantity, quantity, afterQuantity,
                    businessType, businessNo, operator, remark);

            return true;
        } else {
            // 库存不存在，创建新库存
            // 检查物料、仓库、库位是否存在
            if (StringUtils.isBlank(inventory.getMaterialCode())) {
                throw new JeecgBootException("物料编码不能为空");
            }

            if (StringUtils.isBlank(inventory.getWarehouseId())) {
                throw new JeecgBootException("仓库ID不能为空");
            }

            WmsMaterial material = materialService.getByCode(inventory.getMaterialCode());
            if (material == null) {
                throw new JeecgBootException("物料不存在：" + inventory.getMaterialCode());
            }

            WmsWarehouse warehouse = warehouseService.getById(inventory.getWarehouseId());
            if (warehouse == null) {
                throw new JeecgBootException("仓库不存在：" + inventory.getWarehouseId());
            }

            if (StringUtils.isNotBlank(inventory.getLocationId())) {
                WmsWarehouseLocation location = locationService.getById(inventory.getLocationId());
                if (location == null) {
                    throw new JeecgBootException("库位不存在：" + inventory.getLocationId());
                }
            }

            // 创建新库存
            WmsInventory newInventory = new WmsInventory();
            newInventory.setId(UUIDGenerator.generate());
            newInventory.setMaterialCode(inventory.getMaterialCode());
            newInventory.setMaterialName(material.getMaterialName());
            newInventory.setMaterialType(Integer.parseInt(material.getMaterialType()));
            newInventory.setSpecification(material.getSpecification());
            newInventory.setColor(material.getColor());
            newInventory.setUnit(material.getUnit());
            newInventory.setWarehouseId(inventory.getWarehouseId());
            newInventory.setLocationId(inventory.getLocationId());
            newInventory.setQuantity(quantity);
            newInventory.setAvailableQuantity(quantity);
            newInventory.setLockedQuantity(BigDecimal.ZERO);
            newInventory.setBatchNo(inventory.getBatchNo());
            newInventory.setSupplier(inventory.getSupplier());
            newInventory.setInboundTime(new Date());
            newInventory.setRemark(inventory.getRemark());
            newInventory.setCreateBy(operator);
            newInventory.setCreateTime(new Date());
            newInventory.setUpdateBy(operator);
            newInventory.setUpdateTime(new Date());
            newInventory.setTenantId(inventory.getTenantId());

            save(newInventory);

            // 记录库存流水
            afterQuantity = quantity;
            inventoryHistoryService.recordHistory(newInventory, beforeQuantity, quantity, afterQuantity,
                    businessType, businessNo, operator, remark);

            return true;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean outbound(WmsInventory inventory, BigDecimal quantity, Integer businessType, String businessNo, String operator, String remark) {
        if (inventory == null) {
            throw new JeecgBootException("库存信息不能为空");
        }

        if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
            throw new JeecgBootException("出库数量必须大于0");
        }

        // 查询库存是否存在
        WmsInventory existInventory = findByMaterialAndWarehouse(inventory.getMaterialCode(), inventory.getWarehouseId(), inventory.getLocationId());

        if (existInventory == null) {
            throw new JeecgBootException("库存不存在");
        }

        // 检查库存是否足够
        BigDecimal beforeQuantity = existInventory.getQuantity() != null ? existInventory.getQuantity() : BigDecimal.ZERO;
        if (beforeQuantity.compareTo(quantity) < 0) {
            throw new JeecgBootException("库存不足，当前库存：" + beforeQuantity + "，需要出库：" + quantity);
        }

        // 检查可用库存是否足够
        BigDecimal availableQuantity = existInventory.getAvailableQuantity() != null ?
                existInventory.getAvailableQuantity() : BigDecimal.ZERO;
        if (availableQuantity.compareTo(quantity) < 0) {
            throw new JeecgBootException("可用库存不足，当前可用库存：" + availableQuantity + "，需要出库：" + quantity);
        }

        // 更新库存
        BigDecimal afterQuantity = beforeQuantity.subtract(quantity);

        existInventory.setQuantity(afterQuantity);
        existInventory.setAvailableQuantity(availableQuantity.subtract(quantity));
        existInventory.setUpdateBy(operator);
        existInventory.setUpdateTime(new Date());

        updateById(existInventory);

        // 记录库存流水
        inventoryHistoryService.recordHistory(existInventory, beforeQuantity, quantity.negate(), afterQuantity,
                businessType, businessNo, operator, remark);

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean adjust(WmsInventory inventory, BigDecimal quantity, Integer businessType, String businessNo, String operator, String remark) {
        if (inventory == null) {
            throw new JeecgBootException("库存信息不能为空");
        }

//        if (quantity == null || quantity.compareTo(BigDecimal.ZERO) < 0) {
//            throw new JeecgBootException("调整数量不能小于0");
//        }

        // 查询库存是否存在
        WmsInventory existInventory = findByMaterialAndWarehouse(inventory.getMaterialCode(), inventory.getWarehouseId(), inventory.getLocationId());

        if (existInventory == null) {
            throw new JeecgBootException("库存不存在");
        }

        // 计算调整量
        BigDecimal beforeQuantity = existInventory.getQuantity() != null ? existInventory.getQuantity() : BigDecimal.ZERO;
        //计算变更数量 变更数量 = 变更后-变更前
        BigDecimal changeQuantity = quantity.subtract(beforeQuantity);

        // 更新库存
        existInventory.setQuantity(quantity);
        existInventory.setAvailableQuantity(quantity);

        // 记录库存流水
        inventoryHistoryService.recordHistory(existInventory, beforeQuantity, changeQuantity, quantity,
                businessType, businessNo, operator, DateUtils.formatDateTime() + " " + remark);

        if(existInventory.getQuantity() == BigDecimal.ZERO){
            removeById(existInventory);
        }else {
            updateById(existInventory);
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean move(WmsInventory inventory, String targetWarehouseId, String targetLocationId, BigDecimal quantity,
                        Integer outboundBusinessType, Integer inboundBusinessType, String businessNo, String operator, String remark) {
        if (inventory == null) {
            throw new JeecgBootException("库存信息不能为空");
        }

        if (StringUtils.isBlank(targetWarehouseId)) {
            throw new JeecgBootException("目标仓库不能为空");
        }

        if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
            throw new JeecgBootException("移动数量必须大于0");
        }

        // 如果业务单号为空，生成一个
        if (StringUtils.isBlank(businessNo)) {
            businessNo = "MOVE-" + System.currentTimeMillis();
        }

        // 查询源库存是否存在
        WmsInventory sourceInventory = findByMaterialAndWarehouse(inventory.getMaterialCode(), inventory.getWarehouseId(), inventory.getLocationId());

        if (sourceInventory == null) {
            throw new JeecgBootException("源库存不存在");
        }

        // 检查库存是否足够
        BigDecimal beforeQuantity = sourceInventory.getQuantity() != null ? sourceInventory.getQuantity() : BigDecimal.ZERO;
        if (beforeQuantity.compareTo(quantity) < 0) {
            throw new JeecgBootException("库存不足，当前库存：" + beforeQuantity + "，需要移动：" + quantity);
        }

        // 检查可用库存是否足够
        BigDecimal availableQuantity = sourceInventory.getAvailableQuantity() != null ?
                sourceInventory.getAvailableQuantity() : BigDecimal.ZERO;
        if (availableQuantity.compareTo(quantity) < 0) {
            throw new JeecgBootException("可用库存不足，当前可用库存：" + availableQuantity + "，需要移动：" + quantity);
        }

        // 查询目标库存是否存在
        WmsInventory targetInventory = findByMaterialAndWarehouse(inventory.getMaterialCode(), targetWarehouseId, targetLocationId);

        // 源库存出库
        BigDecimal sourceAfterQuantity = beforeQuantity.subtract(quantity);
        sourceInventory.setQuantity(sourceAfterQuantity);
        sourceInventory.setAvailableQuantity(availableQuantity.subtract(quantity));
        sourceInventory.setUpdateBy(operator);
        sourceInventory.setUpdateTime(new Date());

        updateById(sourceInventory);

        // 记录源库存流水
        inventoryHistoryService.recordHistory(sourceInventory, beforeQuantity, quantity.negate(), sourceAfterQuantity,
                outboundBusinessType, businessNo, operator, remark + " - 移出");

        // 目标库存入库
        if (targetInventory != null) {
            // 目标库存已存在，更新数量
            BigDecimal targetBeforeQuantity = targetInventory.getQuantity() != null ? targetInventory.getQuantity() : BigDecimal.ZERO;
            BigDecimal targetAfterQuantity = targetBeforeQuantity.add(quantity);

            targetInventory.setQuantity(targetAfterQuantity);
            targetInventory.setAvailableQuantity(targetInventory.getAvailableQuantity() != null ?
                    targetInventory.getAvailableQuantity().add(quantity) : quantity);
            targetInventory.setUpdateBy(operator);
            targetInventory.setUpdateTime(new Date());

            updateById(targetInventory);

            // 记录目标库存流水
            inventoryHistoryService.recordHistory(targetInventory, targetBeforeQuantity, quantity, targetAfterQuantity,
                    inboundBusinessType, businessNo, operator, remark + " - 移入");
        } else {
            // 目标库存不存在，创建新库存
            WmsInventory newInventory = new WmsInventory();
            newInventory.setId(UUIDGenerator.generate());
            newInventory.setMaterialCode(inventory.getMaterialCode());
            newInventory.setMaterialName(inventory.getMaterialName());
            newInventory.setMaterialType(inventory.getMaterialType());
            newInventory.setSpecification(inventory.getSpecification());
            newInventory.setColor(inventory.getColor());
            newInventory.setUnit(inventory.getUnit());
            newInventory.setWarehouseId(targetWarehouseId);
            newInventory.setLocationId(targetLocationId);
            newInventory.setQuantity(quantity);
            newInventory.setAvailableQuantity(quantity);
            newInventory.setLockedQuantity(BigDecimal.ZERO);
            newInventory.setBatchNo(inventory.getBatchNo());
            newInventory.setSupplier(inventory.getSupplier());
            newInventory.setInboundTime(new Date());
            newInventory.setRemark(inventory.getRemark());
            newInventory.setCreateBy(operator);
            newInventory.setCreateTime(new Date());
            newInventory.setUpdateBy(operator);
            newInventory.setUpdateTime(new Date());
            newInventory.setTenantId(inventory.getTenantId());

            save(newInventory);

            // 记录目标库存流水
            inventoryHistoryService.recordHistory(newInventory, BigDecimal.ZERO, quantity, quantity,
                    inboundBusinessType, businessNo, operator, remark + " - 移入");
        }

        return true;
    }

    /**
     * 带成本的入库
     * <p>
     * 功能说明:
     * 1. 一个库位只能存放一种物料，如果库位已存放其他物料，则会抛出异常
     * 2. 如果物料编号和库位信息一致，则会更新库存数量而不是新增库存记录
     * 3. 入库会自动计算平均单位成本和总成本
     * 4. 会记录库存历史
     *
     * @param inventory    库存对象
     * @param quantity     入库数量
     * @param unitCost     单位成本
     * @param businessType 业务类型
     * @param businessNo   业务单号
     * @param operator     操作人
     * @param remark       备注
     * @return 操作结果
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean inboundWithCost(WmsInventory inventory, BigDecimal quantity, BigDecimal unitCost, Integer businessType, String businessNo, String operator, String remark) {
        if (inventory == null || quantity == null || unitCost == null || businessType == null) {
            return false;
        }

        // 首先检查库位是否已存在其他物料
        if (StringUtils.isNotBlank(inventory.getLocationId())) {
            // 查询该库位是否已存在库存记录
            QueryWrapper<WmsInventory> locationCheck = new QueryWrapper<>();
            locationCheck.eq("warehouse_id", inventory.getWarehouseId())
                    .eq("location_id", inventory.getLocationId())
                    .ne("material_code", inventory.getMaterialCode()); // 排除当前物料

            // 检查库位是否已存放其他物料
            long count = this.count(locationCheck);
            if (count > 0) {
                log.error("库位 {} 已存放其他物料，一个库位只能存放一种物料", inventory.getLocationId());
                throw new JeecgBootException("库位已存放其他物料，一个库位只能存放一种物料");
            }
        }

        // 查询是否已存在相同条件的库存记录
        QueryWrapper<WmsInventory> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("material_code", inventory.getMaterialCode())
                .eq("warehouse_id", inventory.getWarehouseId());

        // 如果指定了库位，则按库位查询
        if (StringUtils.isNotBlank(inventory.getLocationId())) {
            queryWrapper.eq("location_id", inventory.getLocationId());
        }

        // 如果指定了批次号，则按批次号查询
        if (StringUtils.isNotBlank(inventory.getBatchNo())) {
            queryWrapper.eq("batch_no", inventory.getBatchNo());
        }

        // 检查是否是余料入库(businessType=12)
        boolean isSurplusInbound = businessType == 12;

        // 余料入库特殊处理
        if (isSurplusInbound) {
            // 记录源物料和余料信息到历史表中
            WmsInventoryHistory history = new WmsInventoryHistory();
            history.setId(UUID.randomUUID().toString());
            history.setMaterialCode(inventory.getMaterialCode());
            history.setMaterialName(inventory.getMaterialName());
            history.setMaterialType(inventory.getMaterialType());
            history.setSpecification(inventory.getSpecification());
            history.setColor(inventory.getColor());
            history.setUnit(inventory.getUnit());
            history.setWarehouseId(inventory.getWarehouseId());
            history.setLocationId(inventory.getLocationId());
            history.setBusinessType(businessType);
            history.setBusinessNo(businessNo);
            history.setBeforeQuantity(BigDecimal.ZERO);
            history.setChangeQuantity(quantity);
            history.setAfterQuantity(quantity);
            history.setBatchNo(inventory.getBatchNo());
            history.setSupplier(inventory.getSupplier());
            history.setOperator(operator);
            history.setOperateTime(new Date());
            history.setRemark(remark);
            history.setCreateBy(operator);
            history.setCreateTime(new Date());
            history.setUnitCost(unitCost);
            history.setBeforeTotalCost(BigDecimal.ZERO);
            history.setChangeTotalCost(unitCost.multiply(quantity));
            history.setAfterTotalCost(unitCost.multiply(quantity));

            // 直接设置余料特有字段
            history.setSourceMaterialId(inventory.getSourceMaterialId());
            history.setSurplusLength(inventory.getSurplusLength());
            history.setProductionOrderId(inventory.getProductionOrderId());

            // 保存余料入库历史记录
            inventoryHistoryService.save(history);
        }

        // 查询库存记录
        WmsInventory existInventory = this.getOne(queryWrapper);

        // 如果库存记录不存在，则新增
        if (existInventory == null) {
            // 设置库存记录
            inventory.setQuantity(quantity);
            inventory.setAvailableQuantity(quantity);
            inventory.setLockedQuantity(BigDecimal.ZERO);
            inventory.setUnitCost(unitCost);
            inventory.setTotalCost(unitCost.multiply(quantity));
            inventory.setInboundTime(new Date());
            inventory.setCreateBy(operator);
            inventory.setCreateTime(new Date());

            // 保存库存记录
            this.save(inventory);

            // 获取新增的库存ID
            existInventory = this.getOne(queryWrapper);
        } else {
            // 如果库存记录已存在，则更新
            BigDecimal beforeQuantity = existInventory.getQuantity();
            BigDecimal beforeTotalCost = existInventory.getTotalCost();

            // 计算新的总成本和平均单位成本
            BigDecimal newTotalCost = beforeTotalCost.add(unitCost.multiply(quantity));
            BigDecimal newQuantity = beforeQuantity.add(quantity);
            BigDecimal newUnitCost = newTotalCost.divide(newQuantity, 6, RoundingMode.HALF_UP);

            // 更新库存记录
            existInventory.setQuantity(newQuantity);
            existInventory.setAvailableQuantity(existInventory.getAvailableQuantity().add(quantity));
            existInventory.setUnitCost(newUnitCost);
            existInventory.setTotalCost(newTotalCost);
            existInventory.setUpdateBy(operator);
            existInventory.setUpdateTime(new Date());

            // 保存更新的库存记录
            this.updateById(existInventory);
        }

        // 如果不是余料入库，则记录普通入库历史
        if (!isSurplusInbound) {
            // 创建入库历史记录
            WmsInventoryHistory history = new WmsInventoryHistory();
            history.setId(UUID.randomUUID().toString());
            history.setInventoryId(existInventory.getId());
            history.setMaterialCode(inventory.getMaterialCode());
            history.setMaterialName(inventory.getMaterialName());
            history.setMaterialType(inventory.getMaterialType());
            history.setSpecification(inventory.getSpecification());
            history.setColor(inventory.getColor());
            history.setUnit(inventory.getUnit());
            history.setWarehouseId(inventory.getWarehouseId());
            history.setLocationId(inventory.getLocationId());
            history.setBusinessType(businessType);
            history.setBusinessNo(businessNo);
            history.setBeforeQuantity(existInventory.getQuantity().subtract(quantity));
            history.setChangeQuantity(quantity);
            history.setAfterQuantity(existInventory.getQuantity());
            history.setBatchNo(inventory.getBatchNo());
            history.setSupplier(inventory.getSupplier());
            history.setOperator(operator);
            history.setOperateTime(new Date());
            history.setRemark(remark);
            history.setCreateBy(operator);
            history.setCreateTime(new Date());
            history.setUnitCost(unitCost);
            history.setBeforeTotalCost(existInventory.getTotalCost().subtract(unitCost.multiply(quantity)));
            history.setChangeTotalCost(unitCost.multiply(quantity));
            history.setAfterTotalCost(existInventory.getTotalCost());

            // 保存入库历史记录
            inventoryHistoryService.save(history);
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean outboundWithCost(WmsInventory inventory, BigDecimal quantity, Integer businessType,
                                    String businessNo, String operator, String remark) {
        if (inventory == null) {
            throw new JeecgBootException("库存信息不能为空");
        }

        if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
            throw new JeecgBootException("出库数量必须大于0");
        }

        // 查询库存是否存在
        WmsInventory existInventory = findByMaterialAndWarehouse(inventory.getMaterialCode(), inventory.getWarehouseId(), inventory.getLocationId());

        if (existInventory == null) {
            throw new JeecgBootException("库存不存在");
        }

        // 检查库存是否足够
        BigDecimal beforeQuantity = existInventory.getQuantity() != null ? existInventory.getQuantity() : BigDecimal.ZERO;
        if (beforeQuantity.compareTo(quantity) < 0) {
            throw new JeecgBootException("库存不足，当前库存：" + beforeQuantity + "，需要出库：" + quantity);
        }

        // 检查可用库存是否足够
        BigDecimal availableQuantity = existInventory.getAvailableQuantity() != null ?
                existInventory.getAvailableQuantity() : BigDecimal.ZERO;
        if (availableQuantity.compareTo(quantity) < 0) {
            throw new JeecgBootException("可用库存不足，当前可用库存：" + availableQuantity + "，需要出库：" + quantity);
        }

        // 更新库存和成本
        BigDecimal afterQuantity = beforeQuantity.subtract(quantity);

        // 计算成本变动
        BigDecimal unitCost = existInventory.getUnitCost() != null ? existInventory.getUnitCost() : BigDecimal.ZERO;
        BigDecimal beforeTotalCost = existInventory.getTotalCost() != null ? existInventory.getTotalCost() : BigDecimal.ZERO;
        BigDecimal changeTotalCost = quantity.multiply(unitCost).negate(); // 出库为负数
        BigDecimal afterTotalCost = beforeTotalCost.add(changeTotalCost);

        existInventory.setQuantity(afterQuantity);
        existInventory.setAvailableQuantity(availableQuantity.subtract(quantity));
        existInventory.setTotalCost(afterTotalCost);
        existInventory.setUpdateBy(operator);
        existInventory.setUpdateTime(new Date());

        updateById(existInventory);

        // 记录库存流水（包含成本信息）
        inventoryHistoryService.recordHistoryWithCost(existInventory, beforeQuantity, quantity.negate(), afterQuantity,
                beforeTotalCost, changeTotalCost, afterTotalCost, businessType, businessNo, operator, remark);

        return true;
    }

    /**
     * 库存成本调整
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean adjustCost(WmsInventory inventory, BigDecimal newUnitCost, Integer businessType, String businessNo, String operator, String remark) {
        if (inventory == null) {
            throw new JeecgBootException("库存信息不能为空");
        }

        if (newUnitCost == null || newUnitCost.compareTo(BigDecimal.ZERO) < 0) {
            throw new JeecgBootException("单位成本不能小于0");
        }

        // 查询库存是否存在
        WmsInventory existInventory = findByMaterialAndWarehouse(inventory.getMaterialCode(), inventory.getWarehouseId(), inventory.getLocationId());

        if (existInventory == null) {
            throw new JeecgBootException("库存不存在");
        }

        // 计算成本变动
        BigDecimal quantity = existInventory.getQuantity() != null ? existInventory.getQuantity() : BigDecimal.ZERO;
        BigDecimal oldUnitCost = existInventory.getUnitCost() != null ? existInventory.getUnitCost() : BigDecimal.ZERO;
        BigDecimal beforeTotalCost = oldUnitCost.multiply(quantity);
        BigDecimal afterTotalCost = newUnitCost.multiply(quantity);
        BigDecimal changeTotalCost = afterTotalCost.subtract(beforeTotalCost);

        // 更新库存成本
        existInventory.setUnitCost(newUnitCost);
        existInventory.setTotalCost(afterTotalCost);
        existInventory.setUpdateBy(operator);
        existInventory.setUpdateTime(new Date());

        updateById(existInventory);

        // 记录库存流水（包含成本信息）
        inventoryHistoryService.recordHistoryWithCost(existInventory, quantity, BigDecimal.ZERO, quantity,
                beforeTotalCost, changeTotalCost, afterTotalCost, businessType, businessNo, operator, remark);

        return true;
    }

    /**
     * 查询物料在特定仓库的库存
     */
    @Override
    public List<WmsInventoryVO> queryByMaterialAndWarehouse(String materialId, String warehouseId) {
        if (StringUtils.isBlank(materialId) || StringUtils.isBlank(warehouseId)) {
            throw new RuntimeException("物料编码和仓库ID不能为空");
        }
        WmsMaterial material = materialService.getById(materialId);

        // 构建查询条件
        Map<String, Object> query = new HashMap<>();
        query.put("materialCode", material.getMaterialCode());
        query.put("warehouseId", warehouseId);

        // 查询库存列表
        List<WmsInventoryVO> inventoryList = baseMapper.queryInventoryList(query);

        // 查询库位信息，填充库位容量
        if (inventoryList != null && !inventoryList.isEmpty()) {
            // 获取所有库位ID
            List<String> locationIds = inventoryList.stream()
                    .map(WmsInventoryVO::getLocationId)
                    .filter(StringUtils::isNotBlank)
                    .distinct()
                    .collect(Collectors.toList());

            if (!locationIds.isEmpty()) {
                // 批量查询库位信息
                List<WmsWarehouseLocation> locationList = locationService.listByIds(locationIds);
                Map<String, BigDecimal> locationCapacityMap = locationList.stream()
                        .collect(Collectors.toMap(WmsWarehouseLocation::getId,
                                location -> location.getCapacity() != null ? location.getCapacity() : BigDecimal.ZERO,
                                (k1, k2) -> k1));

                // 填充库位容量
                for (WmsInventoryVO vo : inventoryList) {
                    if (StringUtils.isNotBlank(vo.getLocationId()) && locationCapacityMap.containsKey(vo.getLocationId())) {
                        vo.setCapacity(locationCapacityMap.get(vo.getLocationId()));
                    }
                }
            }
        }

        return inventoryList;
    }

    /**
     * 查询库存 - 仅使用物料编码、仓库ID和库位ID作为条件
     *
     * @param materialCode 物料编码
     * @param warehouseId  仓库ID
     * @param locationId   库位ID
     * @param batchNo      批次号（仅用于记录，不作为查询条件）
     * @return 库存对象，如果不存在则返回null
     */
    public WmsInventory queryInventory(String materialCode, String warehouseId, String locationId, String batchNo, String materialColor) {
        log.info("查询库存 - materialCode: {}, warehouseId: {}, locationId: {}", materialCode, warehouseId, locationId);

        // 构建查询条件，只使用物料编码、仓库ID和库位ID
        LambdaQueryWrapper<WmsInventory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(materialCode), WmsInventory::getMaterialCode, materialCode)
                .eq(StringUtils.isNotBlank(warehouseId), WmsInventory::getWarehouseId, warehouseId)
                .eq(StringUtils.isNotBlank(locationId), WmsInventory::getLocationId, locationId)
                .eq(StringUtils.isNotBlank(materialColor), WmsInventory::getColor, materialColor);

        // 不再使用批次号作为查询条件，以便实现同一物料、同一库位的库存累加

        // 查询库存
        WmsInventory inventory = this.getOne(queryWrapper);
        if (inventory != null) {
            log.info("找到库存记录 - 数量: {}, 批次号: {}", inventory.getQuantity(), inventory.getBatchNo());
        } else {
            log.info("未找到库存记录，将创建新库存");
        }
        return inventory;
    }

    /**
     * 带成本的入库，使用参数映射
     *
     * @param params 入库参数映射，包含物料信息、仓库库位、数量、成本等
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean inboundWithCostAndParams(Map<String, Object> params) {
        try {
            // 提取参数
            String materialImage = "";
            if (params.get("materialId") != null) {
                String materialId = (String) params.get("materialId");
                WmsMaterial material = materialService.getById(materialId);
                materialImage = material.getMaterialImage();
            }

            String materialCode = (String) params.get("materialCode");
            String materialName = (String) params.get("materialName");
            Object materialTypeObj = params.get("materialType");
            String materialType = materialTypeObj != null ? materialTypeObj.toString() : null;
            String specification = (String) params.get("specification");
            String unit = (String) params.get("unit");
            String warehouseId = (String) params.get("warehouseId");
            String locationId = (String) params.get("locationId");
            String materialColor = (String) params.get("materialColor");
            BigDecimal quantity = null;
            Object quantityObj = params.get("quantity");
            if (quantityObj instanceof BigDecimal) {
                quantity = (BigDecimal) quantityObj;
            } else if (quantityObj instanceof Number) {
                quantity = new BigDecimal(((Number) quantityObj).toString());
            } else if (quantityObj instanceof String) {
                quantity = new BigDecimal((String) quantityObj);
            }

            // 获取是否更新成本的标志
            Boolean updateCost = true; // 默认更新成本
            Object updateCostObj = params.get("updateCost");
            if (updateCostObj instanceof Boolean) {
                updateCost = (Boolean) updateCostObj;
            } else if (updateCostObj instanceof String) {
                updateCost = Boolean.parseBoolean((String) updateCostObj);
            }

            BigDecimal unitCost = null;
            Object unitCostObj = params.get("unitCost");
            if (unitCostObj instanceof BigDecimal) {
                unitCost = (BigDecimal) unitCostObj;
            } else if (unitCostObj instanceof Number) {
                unitCost = new BigDecimal(((Number) unitCostObj).toString());
            } else if (unitCostObj instanceof String && StringUtils.isNotBlank((String) unitCostObj)) {
                unitCost = new BigDecimal((String) unitCostObj);
            }

            // 如果不需要更新成本或没有有效的成本信息，则设置unitCost为null
            if (!updateCost || unitCost == null || unitCost.compareTo(BigDecimal.ZERO) <= 0) {
                unitCost = null;
            }

            String batchNo = (String) params.get("batchNo");
            Integer businessType = null;
            Object businessTypeObj = params.get("businessType");
            if (businessTypeObj instanceof Integer) {
                businessType = (Integer) businessTypeObj;
            } else if (businessTypeObj instanceof String) {
                businessType = Integer.parseInt((String) businessTypeObj);
            }
            String businessNo = (String) params.get("businessNo");
            String operator = (String) params.get("operator");
            String remark = (String) params.get("remark");

            // 获取操作时间
            Date operateTime = null;
            Object operateTimeObj = params.get("operateTime");
            if (operateTimeObj instanceof Date) {
                operateTime = (Date) operateTimeObj;
            } else if (operateTimeObj instanceof String && StringUtils.isNotBlank((String) operateTimeObj)) {
                try {
                    // 尝试解析日期字符串，支持多种格式
                    SimpleDateFormat[] formats = {
                            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),
                            new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"),
                            new SimpleDateFormat("yyyy-MM-dd"),
                            new SimpleDateFormat("yyyy/MM/dd")
                    };

                    String dateStr = (String) operateTimeObj;
                    for (SimpleDateFormat format : formats) {
                        try {
                            operateTime = format.parse(dateStr);
                            break;
                        } catch (Exception e) {
                            // 继续尝试下一种格式
                        }
                    }
                } catch (Exception e) {
                    log.warn("解析操作时间失败: {}", operateTimeObj);
                }
            }

            // 如果没有指定操作时间，使用当前时间
            if (operateTime == null) {
                operateTime = new Date();
            }

            // 参数校验
            if (StringUtils.isBlank(materialCode)) {
                log.error("物料编码不能为空");
                return false;
            }

            if (StringUtils.isBlank(warehouseId)) {
                log.error("仓库ID不能为空");
                return false;
            }

            if (StringUtils.isBlank(locationId)) {
                log.error("库位ID不能为空");
                return false;
            }

            if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
                log.error("入库数量必须大于0");
                return false;
            }

            // 查询库存是否已存在
            WmsInventory inventory = queryInventory(materialCode, warehouseId, locationId, batchNo, materialColor);

            // 如果库存不存在，则创建新库存
            BigDecimal originalQuantity = null;
            BigDecimal newQuantity = null;
            if (inventory == null) {
                inventory = new WmsInventory();
                inventory.setMaterialCode(materialCode);
                inventory.setMaterialName(materialName);
                if (oConvertUtils.isNotEmpty(materialImage)) {
                    inventory.setMaterialImages(materialImage);
                }
                if (materialType != null) {
                    try {
                        inventory.setMaterialType(Integer.parseInt(materialType));
                    } catch (NumberFormatException e) {
                        log.warn("物料类型格式错误: {}", materialType);
                    }
                }
                inventory.setSpecification(specification);
                inventory.setUnit(unit);
                inventory.setWarehouseId(warehouseId);
                inventory.setLocationId(locationId);
                inventory.setQuantity(quantity);
                // 设置可用数量、锁定数量和预出库数量
                inventory.setAvailableQuantity(quantity);
                inventory.setLockedQuantity(BigDecimal.ZERO);
                inventory.setPreOutboundQuantity(BigDecimal.ZERO);
                inventory.setUnitCost(unitCost);
                inventory.setBatchNo(batchNo); // 记录首次入库的批次号
                inventory.setColor(materialColor);

                // 计算总成本
                if (unitCost != null) {
                    BigDecimal totalCost = unitCost.multiply(quantity);
                    inventory.setTotalCost(totalCost);
                }

                // 保存库存
                boolean saveResult = save(inventory);
                if (!saveResult) {
                    log.error("保存库存失败");
                    return false;
                }
                originalQuantity = BigDecimal.valueOf(0);
                newQuantity = inventory.getQuantity();
                quantity = inventory.getQuantity();
            } else {
                // 如果库存已存在，则更新库存数量和成本
                originalQuantity = inventory.getQuantity() != null ? inventory.getQuantity() : BigDecimal.ZERO;
                BigDecimal originalAvailableQuantity = inventory.getAvailableQuantity() != null ? inventory.getAvailableQuantity() : BigDecimal.ZERO;
                BigDecimal originalTotalCost = inventory.getTotalCost() != null ? inventory.getTotalCost() : BigDecimal.ZERO;
                newQuantity = originalQuantity.add(quantity);
                // 计算新的可用数量
                BigDecimal newAvailableQuantity = originalAvailableQuantity.add(quantity);

                // 计算加权平均成本
                BigDecimal newTotalCost;
                BigDecimal newUnitCost;

                if (unitCost != null && updateCost) {
                    // 新入库物料的总成本
                    BigDecimal inboundTotalCost = unitCost.multiply(quantity);

                    // 计算新的总成本
                    newTotalCost = originalTotalCost.add(inboundTotalCost);

                    // 计算新的单位成本（加权平均）
                    if (newQuantity.compareTo(BigDecimal.ZERO) > 0) {
                        newUnitCost = newTotalCost.divide(newQuantity, 6, BigDecimal.ROUND_HALF_UP);
                    } else {
                        newUnitCost = unitCost;
                    }
                } else {
                    // 如果没有提供单位成本，则使用原有单位成本
                    newUnitCost = inventory.getUnitCost();
                    if (newUnitCost != null) {
                        newTotalCost = newUnitCost.multiply(newQuantity);
                    } else {
                        newTotalCost = originalTotalCost;
                    }
                }

                // 更新库存
                inventory.setQuantity(newQuantity);
                // 更新可用数量
                inventory.setAvailableQuantity(newAvailableQuantity);
                // 只有在需要更新成本且有有效成本时才更新成本信息
                if (updateCost && unitCost != null) {
                    inventory.setUnitCost(newUnitCost);
                    inventory.setTotalCost(newTotalCost);
                }
                if (oConvertUtils.isNotEmpty(materialImage)) {
                    inventory.setMaterialImages(materialImage);
                }

                // 不更新批次号，保留首次入库的批次号，或使用最新批次号更新
                // 这里可以根据实际业务需要决定是否更新批次号
                // 例如：如果想要保留最新批次号，可以使用下面的代码
                if (StringUtils.isNotBlank(batchNo)) {
                    // 记录原批次号用于记录
                    String oldBatchNo = inventory.getBatchNo();
                    // 如果新批次号与原批次号不同，则在日志中记录变更
                    if (!batchNo.equals(oldBatchNo)) {
                        log.info("库存批次号更新：物料={}, 库位={}, 旧批次号={}, 新批次号={}",
                                materialCode, locationId, oldBatchNo, batchNo);
                        // 更新为最新批次号
                        inventory.setBatchNo(batchNo);
                    }
                }

                // 保存更新
                boolean updateResult = updateById(inventory);
                if (!updateResult) {
                    log.error("更新库存失败");
                    return false;
                }
            }

            // 创建库存历史记录
            WmsInventoryHistory history = new WmsInventoryHistory();
            history.setInventoryId(inventory.getId());
            history.setMaterialCode(materialCode);
            history.setMaterialName(materialName);
            if (materialType != null) {
                try {
                    history.setMaterialType(Integer.parseInt(materialType));
                } catch (NumberFormatException e) {
                    log.warn("物料类型格式错误: {}", materialType);
                }
            }
            history.setSpecification(specification);
            history.setUnit(unit);
            history.setWarehouseId(warehouseId);
            history.setLocationId(locationId);
            history.setBeforeQuantity(originalQuantity);
            history.setChangeQuantity(quantity);
            history.setAfterQuantity(newQuantity);

            // 获取仓库和库位名称
            WmsWarehouse warehouse = warehouseService.getById(warehouseId);
            if (warehouse != null) {
                history.setWarehouseName(warehouse.getWarehouseName());
            }

            WmsWarehouseLocation location = locationService.getById(locationId);
            if (location != null) {
                history.setLocationName(location.getLocationName());
            }

            // 只有在需要更新成本且有有效成本时才设置成本信息
            if (updateCost && unitCost != null) {
                history.setUnitCost(unitCost);
                // 计算成本变动金额
                BigDecimal inboundTotalCost = unitCost.multiply(quantity);
                history.setChangeTotalCost(inboundTotalCost);

                // 设置变动前总成本
                BigDecimal beforeTotalCost = inventory.getTotalCost().subtract(inboundTotalCost);
                history.setBeforeTotalCost(beforeTotalCost);

                // 设置变动后总成本
                history.setAfterTotalCost(inventory.getTotalCost());
            } else if (inventory.getUnitCost() != null) {
                // 如果不更新成本但库存有单位成本，使用库存的单位成本
                history.setUnitCost(inventory.getUnitCost());
                // 成本变动金额和总成本保持为0
                history.setChangeTotalCost(BigDecimal.ZERO);
                history.setBeforeTotalCost(inventory.getTotalCost());
                history.setAfterTotalCost(inventory.getTotalCost());
            }

            history.setBatchNo(batchNo);  // 使用当前入库的批次号，记录在历史记录中
            history.setBusinessType(businessType);
            history.setBusinessNo(businessNo);
            history.setOperator(operator);
            history.setOperateTime(operateTime); // 设置操作时间
            history.setRemark(remark);

            // 如果原库存已有批次号且与当前入库批次号不同，在备注中记录批次号变更
            if (StringUtils.isNotBlank(inventory.getBatchNo()) &&
                    StringUtils.isNotBlank(batchNo) &&
                    !inventory.getBatchNo().equals(batchNo)) {
                String batchChangeRemark = "批次号变更: " + inventory.getBatchNo() + " -> " + batchNo;
                if (StringUtils.isNotBlank(remark)) {
                    history.setRemark(remark + "; " + batchChangeRemark);
                } else {
                    history.setRemark(batchChangeRemark);
                }
            }

            // 保存历史记录
            boolean historyResult = inventoryHistoryService.save(history);
            if (!historyResult) {
                log.error("保存库存历史记录失败");
                return false;
            }

            return true;
        } catch (Exception e) {
            log.error("入库操作失败", e);
            throw new RuntimeException("入库操作失败: " + e.getMessage());
        }
    }

    @Override
    public List<WmsInventoryVO> queryAvailableInventoryForOutbound(String materialCode, String materialType, BigDecimal requiredQuantity) {
        List<WmsInventoryVO> result = new ArrayList<>();

        try {
            // 构建查询条件
            LambdaQueryWrapper<WmsInventory> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WmsInventory::getMaterialCode, materialCode);
            queryWrapper.gt(WmsInventory::getQuantity, BigDecimal.ZERO);

            if (StringUtils.isNotBlank(materialType)) {
                queryWrapper.eq(WmsInventory::getMaterialType, materialType);
            }

            // 查询库存记录
            List<WmsInventory> inventoryList = this.list(queryWrapper);

            // 转换为VO并设置相关信息
            List<WmsInventoryVO> allInventory = new ArrayList<>();
            for (WmsInventory inventory : inventoryList) {
                WmsInventoryVO vo = new WmsInventoryVO();
                BeanUtils.copyProperties(inventory, vo);

                // 查询并设置仓库名称
                if (StringUtils.isNotBlank(inventory.getWarehouseId())) {
                    WmsWarehouse warehouse = warehouseService.getById(inventory.getWarehouseId());
                    if (warehouse != null) {
                        vo.setWarehouseName(warehouse.getWarehouseName());
                    }
                }

                // 查询并设置库位名称
                if (StringUtils.isNotBlank(inventory.getLocationId())) {
                    WmsWarehouseLocation location = locationService.getById(inventory.getLocationId());
                    if (location != null) {
                        vo.setLocationName(location.getLocationName());
                    }
                }

                // 查询并设置物料名称
                if (StringUtils.isNotBlank(inventory.getMaterialCode())) {
                    WmsMaterial material = materialService.getByCode(inventory.getMaterialCode());
                    if (material != null) {
                        vo.setMaterialName(material.getMaterialName());
                        vo.setSpecification(material.getSpecification());
                        vo.setUnit(material.getUnit());
                    }
                }

                allInventory.add(vo);
            }

            // 按库存数量升序排序，优先使用库存少的
            allInventory.sort((a, b) -> a.getQuantity().compareTo(b.getQuantity()));

            // 组合出库方案
            BigDecimal remainingQuantity = requiredQuantity;
            BigDecimal totalAvailableQuantity = BigDecimal.ZERO;

            // 计算总可用库存
            for (WmsInventoryVO vo : allInventory) {
                totalAvailableQuantity = totalAvailableQuantity.add(vo.getQuantity());
            }

            // 生成出库方案
            for (WmsInventoryVO vo : allInventory) {
                if (remainingQuantity.compareTo(BigDecimal.ZERO) <= 0) {
                    break;
                }

                // 计算当前库位的出库数量
                BigDecimal outboundQuantity = vo.getQuantity().min(remainingQuantity);
                vo.setOutboundQuantity(outboundQuantity);
                vo.setSufficient(totalAvailableQuantity.compareTo(requiredQuantity) >= 0);

                remainingQuantity = remainingQuantity.subtract(outboundQuantity);
                result.add(vo);
            }

            // 如果总库存不足，设置实际可出库数量
            if (totalAvailableQuantity.compareTo(requiredQuantity) < 0) {
                // 在第一个库存记录中标记总库存不足的信息
                if (!result.isEmpty()) {
                    WmsInventoryVO firstVo = result.get(0);
                    firstVo.setTotalAvailableQuantity(totalAvailableQuantity);
                    firstVo.setRequiredQuantity(requiredQuantity);
                    firstVo.setInsufficientStock(true);
                }
            }

            log.info("查询到物料 {} 的可用库存 {} 条记录，生成出库方案 {} 个库位",
                    materialCode, allInventory.size(), result.size());

        } catch (Exception e) {
            log.error("查询可用库存失败", e);
            throw new JeecgBootException("查询可用库存失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 移动端库存查询
     */
    @Override
    public IPage<WmsInventoryVO> queryInventoryForMobile(Page<WmsInventoryVO> page, Map<String, Object> params) {
        log.info("移动端库存查询，参数: {}", params);

        try {
            // 调用Mapper的移动端查询方法
            IPage<WmsInventoryVO> pageList = baseMapper.queryInventoryForMobile(page, params);

            // 计算库存状态（复用现有逻辑）
            if (pageList.getRecords() != null && !pageList.getRecords().isEmpty()) {
                // 按物料编号和型材长度分组，计算总库存
                Map<String, BigDecimal> materialTotalMap = new HashMap<>();

                // 第一次遍历，计算每个物料编号+型材长度的总库存
                for (WmsInventoryVO vo : pageList.getRecords()) {
                    String materialKey = vo.getMaterialCode();
                    // 如果存在型材长度，则将其作为key的一部分
                    if (vo.getSpecification() != null && vo.getSpecification().contains("*")) {
                        materialKey += "_" + vo.getSpecification();
                    }

                    BigDecimal currentTotal = materialTotalMap.getOrDefault(materialKey, BigDecimal.ZERO);
                    currentTotal = currentTotal.add(vo.getQuantity() != null ? vo.getQuantity() : BigDecimal.ZERO);
                    materialTotalMap.put(materialKey, currentTotal);
                }

                // 第二次遍历，根据总库存和物料预警上下限判断库存状态
                for (WmsInventoryVO vo : pageList.getRecords()) {
                    // 获取物料信息
                    WmsMaterial material = materialService.getByCode(vo.getMaterialCode());
                    if (material != null) {
                        String materialKey = vo.getMaterialCode();
                        // 如果存在型材长度，则将其作为key的一部分
                        if (vo.getSpecification() != null && vo.getSpecification().contains("*")) {
                            materialKey += "_" + vo.getSpecification();
                        }

                        // 获取该物料编号+型材长度的总库存
                        BigDecimal totalQuantity = materialTotalMap.getOrDefault(materialKey, BigDecimal.ZERO);

                        // 根据总库存与预警上下限比较设置库存状态
                        if (material.getUpperLimit() != null && totalQuantity.compareTo(material.getUpperLimit()) > 0) {
                            vo.setStockStatus(2); // 超过上限
                            vo.setStockStatusName("超过上限");
                        } else if (material.getLowerLimit() != null && totalQuantity.compareTo(material.getLowerLimit()) < 0) {
                            vo.setStockStatus(3); // 低于下限
                            vo.setStockStatusName("低于下限");
                        } else {
                            vo.setStockStatus(1); // 正常
                            vo.setStockStatusName("正常");
                        }
                    }
                }
            }

            log.info("移动端库存查询完成，返回 {} 条记录", pageList.getRecords().size());
            return pageList;

        } catch (Exception e) {
            log.error("移动端库存查询失败", e);
            throw new JeecgBootException("移动端库存查询失败: " + e.getMessage());
        }
    }

    @Override
    public void exportInventoryList(Map<String, Object> params, HttpServletResponse response) {
        try {
            log.info("开始导出库存列表，查询参数: {}", params);
            
            // 查询库存数据（不分页，获取所有数据）
            List<WmsInventoryVO> inventoryList = baseMapper.queryInventoryList(params);
            
            // 创建工作簿
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("库存列表");
            
            // 创建标题行
            Row headerRow = sheet.createRow(0);
            String[] headers = {"物料编号", "物料名称", "物料系列", "物料颜色", "物料长度(m)", "仓库", "库位", "数量","单位"};
            
            // 设置标题样式
            CellStyle headerStyle = workbook.createCellStyle();
            Font headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerStyle.setFont(headerFont);
            headerStyle.setAlignment(HorizontalAlignment.CENTER);
            headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
                cell.setCellStyle(headerStyle);
                sheet.setColumnWidth(i, 4000); // 设置列宽
            }
            
            // 创建数据行
            CellStyle dataStyle = workbook.createCellStyle();
            dataStyle.setAlignment(HorizontalAlignment.CENTER);
            dataStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            
            for (int i = 0; i < inventoryList.size(); i++) {
                Row dataRow = sheet.createRow(i + 1);
                WmsInventoryVO inventory = inventoryList.get(i);
                
                // 物料编号
                Cell cell0 = dataRow.createCell(0);
                cell0.setCellValue(inventory.getMaterialCode() != null ? inventory.getMaterialCode() : "");
                cell0.setCellStyle(dataStyle);
                
                // 物料名称
                Cell cell1 = dataRow.createCell(1);
                cell1.setCellValue(inventory.getMaterialName() != null ? inventory.getMaterialName() : "");
                cell1.setCellStyle(dataStyle);
                
                // 物料系列
                Cell cell2 = dataRow.createCell(2);
                cell2.setCellValue(inventory.getMaterialSeries() != null ? inventory.getMaterialSeries() : "");
                cell2.setCellStyle(dataStyle);
                
                // 物料颜色
                Cell cell3 = dataRow.createCell(3);
                cell3.setCellValue(inventory.getColor() != null ? inventory.getColor() : "");
                cell3.setCellStyle(dataStyle);
                
                // 物料长度（规格型号）
                Cell cell4 = dataRow.createCell(4);
                cell4.setCellValue(inventory.getMaterialLength() != null ? inventory.getMaterialLength().doubleValue() :0.0);
                cell4.setCellStyle(dataStyle);
                
                // 仓库
                Cell cell5 = dataRow.createCell(5);
                cell5.setCellValue(inventory.getWarehouseName() != null ? inventory.getWarehouseName() : "");
                cell5.setCellStyle(dataStyle);
                
                // 库位
                Cell cell6 = dataRow.createCell(6);
                cell6.setCellValue(inventory.getLocationName() != null ? inventory.getLocationName() : "");
                cell6.setCellStyle(dataStyle);
                
                // 数量
                Cell cell7 = dataRow.createCell(7);
                cell7.setCellValue(inventory.getQuantity() != null ? inventory.getQuantity().doubleValue() : 0.0);
                cell7.setCellStyle(dataStyle);

                // 数量
                Cell cell8 = dataRow.createCell(8);
                cell8.setCellValue(inventory.getUnit() != null ? inventory.getUnit(): "");
                cell8.setCellStyle(dataStyle);
            }
            
            // 设置响应头
            String fileName = "库存列表_" + DateUtils.formatDateTime() + ".xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            
            // 写入响应
            workbook.write(response.getOutputStream());
            workbook.close();
            
            log.info("库存列表导出完成，共导出 {} 条记录", inventoryList.size());
            
        } catch (Exception e) {
            log.error("导出库存列表失败", e);
            throw new JeecgBootException("导出库存列表失败: " + e.getMessage());
        }
    }
}